package com.example.estest.controller;

import com.example.estest.entity.Order;
import com.example.estest.entity.PageResult;
import com.example.estest.entity.User;
import com.sun.org.apache.xpath.internal.operations.Or;
import lombok.AllArgsConstructor;
import org.apache.lucene.queryparser.xml.builders.BooleanQueryBuilder;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.elasticsearch.common.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.naming.ldap.PagedResultsControl;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author whx
 * @date 2022/7/2
 */
@RestController
@RequestMapping("order")
@AllArgsConstructor
public class OrderController {

    private final ElasticsearchRestTemplate restTemplate;

    @GetMapping("getByNo")
    public Order getByNo(String no){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.termsQuery("no",no));
        SearchHit<Order> searchRes = restTemplate.searchOne(queryBuilder.build(), Order.class);
        return searchRes == null ? null : searchRes.getContent();
    }

    @GetMapping("pageByStatus")
    public PageResult<Order> pageByStatus(int page,int size,int ...status){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.termsQuery("status",status)).withPageable(PageRequest.of(page, size));
        SearchHits<Order> search = restTemplate.search(queryBuilder.build(), Order.class);
        List<Order> collect = search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
        return PageResult.data(collect,search.getTotalHits());
    }

    @GetMapping("listGreaterThanAmount")
    public List<Order> listGreaterThanAmount(int page,int size,Double amount){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.rangeQuery("amount").gt(amount)).withPageable(PageRequest.of(page, size));
        SearchHits<Order> search = restTemplate.search(queryBuilder.build(), Order.class);
        return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
    }

    @GetMapping("listMatchAddress")
    public List<Order> listMatchAddress(int page,int size,String address){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.matchQuery("address",address)).withPageable(PageRequest.of(page, size));
        SearchHits<Order> search = restTemplate.search(queryBuilder.build(), Order.class);
        return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
    }

    @GetMapping("listRangeTimeAndStatus")
    public List<Order> listRangeTimeAndStatus(int page, int size, Date startTime, Date endTime, Integer status){
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.termQuery("status",status))
                .must(QueryBuilders.rangeQuery("create_time").gte(startTime).lt(endTime));
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(boolQueryBuilder).withPageable(PageRequest.of(page, size));
        SearchHits<Order> search = restTemplate.search(queryBuilder.build(), Order.class);
        return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
    }

    @GetMapping("listByProductName")
    public List<Order> listByProductName(int page,int size,String name){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.nestedQuery("product",
                QueryBuilders.termQuery("product.name",name),ScoreMode.Max))
                .withPageable(PageRequest.of(page, size));
        SearchHits<Order> search = restTemplate.search(queryBuilder.build(), Order.class);
        return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
    }

    @GetMapping("listByPointAndDistance")
    public List<Order> listByPointAndDistance(int page, int size, Double lat,Double lon, String distance){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder("point");
        distanceQueryBuilder.point(new GeoPoint(lat,lon)).distance(distance);
        queryBuilder.withQuery(distanceQueryBuilder).withPageable(PageRequest.of(page, size));
        SearchHits<Order> search = restTemplate.search(queryBuilder.build(), Order.class);
        return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
    }

}
